import time
from datetime import timedelta, datetime
from typing import Union
from fastapi import HTTPException, status
from jose import jwt
from passlib.context import CryptContext
from fastapi.security import OAuth2PasswordBearer
from fastapi import Depends, HTTPException, status
from jose import jwt, JWTError

from core.config import settings
from models import ZhanUser


class UserVerifyService(object):
    pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

    @staticmethod
    def verify_password(plain_password, hashed_password):
        return UserVerifyService.pwd_context.verify(plain_password, hashed_password)

    @staticmethod
    def get_password_hash(password):
        return UserVerifyService.pwd_context.hash(password)

    @staticmethod
    async def get_user(username: str, pk: int):
        user_item = await ZhanUser.get(pk=pk, username=username)
        if not user_item:
            return False
        return user_item

    @staticmethod
    async def get_user_veirfy_password(username: str, password: str):
        user_item = await ZhanUser.filter(username=username).first()
        if not user_item:
            return False
        if not UserVerifyService.verify_password(password, user_item.password):
            return False
        return user_item

    @staticmethod
    async def authenticate_user(username: str, password: str):
        user = await UserVerifyService.get_user_veirfy_password(username, password)
        if not user:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="Incorrect username or password",
                headers={"WWW-Authenticate": "Bearer"},
            )
        return user

    @staticmethod
    def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None):
        to_encode = data.copy()
        if expires_delta:
            expire = datetime.utcnow() + expires_delta
        else:
            expire = datetime.utcnow() + timedelta(minutes=15)
        to_encode.update({"exp": expire})
        encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM)
        return encoded_jwt

    @staticmethod
    def verify_time(now, expire):
        expire_time = datetime.fromtimestamp(now) + timedelta(minutes=expire)
        if datetime.utcnow() > expire_time:
            return False
        return True

